package com.jse;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.jar.JarFile;

import javax.tools.ToolProvider;

public class Compiler {
	
//	public static URLClassLoader cl;
	public static HashMap<String,Class<?>> CLASS=new HashMap<>();

	/** 运行时动态加载jar包到项目<br/>
	 * loadJars(List.of("D:/work/jsa/lib/mysql-connector-j-8.0.32.jar","D:/work/jsa/lib/protobuf-java-3.19.4.jar"));
	 *  */
	public static void loadJars(List<String> jarFiles) {
	    var urls = new ArrayList<URL>();
	    jarFiles.forEach(jarFilePath->{
	      try {
			urls.add(URI.create("jar:file:/" + jarFilePath + "!/").toURL());
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
	    });
	    var cl = new URLClassLoader(urls.toArray(new java.net.URL[urls.size()]),ClassLoader.getSystemClassLoader());
	    jarFiles.forEach(jarFilePath->{
		try {
			var e = new JarFile(jarFilePath.toString()).entries();
		      while (e.hasMoreElements()) {
		        var je = e.nextElement();
		        if (je.isDirectory() || !je.getName().endsWith(".class")
		        		||je.getName().equals("module-info.class")||je.getName().startsWith("META-INF/")) {
		          continue;
		        }
		        var className = je.getName().substring(0, je.getName().length() - 6);
		        className = className.replaceAll("/", ".");
		        var c = cl.loadClass(className);
		        CLASS.put(className,c);
		      }
		} catch (IOException|NoClassDefFoundError|ClassNotFoundException e) {
			Log.get("compiler").debug("loadjars ["+jarFilePath+"] err:"+e.getMessage());
		}
	    });
	}
	public static Class<?> loadClass(String p,String name) {
		var cl = new SecureClassLoader() {
        @Override
	        protected Class<?> findClass(String name) throws ClassNotFoundException {
	            try {
					byte[] bytes = Files.readAllBytes(Path.of(p));
					return super.defineClass(name, bytes, 0, bytes.length);
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
	        }
		};
//		Thread.currentThread().setContextClassLoader(cl);
		try {
			return cl.loadClass(name);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/** 编译java文件,默认在编译的目录存放 @param java文件 */
	public static boolean compilerJava(String f){//"D:/test/AlTest1.java"
        return ToolProvider.getSystemJavaCompiler().run(null,null,null,"-encoding","UTF-8","-classpath",f.toString(),f)==0;
	}
	public static boolean compilerJavac(String f){//D:/test/AlTest2.java
		try {//"--class-path","D:/test/",
			Process process = Runtime.getRuntime().exec(new String[]{"javac",f});
			int exitVal = process.waitFor();
			if(exitVal!=0) {
				var charset=File.separatorChar=='/'?StandardCharsets.UTF_8:Charset.forName("GBK");//win下用GBK
				System.out.println(new String(process.getErrorStream().readAllBytes(),charset));
				return false;
			}
			return true;
		} catch (IOException | InterruptedException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static void main(String[] args) {
		System.out.println(compilerJava("D:\\work\\jsx\\src\\test\\java\\com\\jse\\http\\Part.java"));
		Class<?> c=loadClass("D:\\work\\jsx\\src\\test\\java\\com\\jse\\http\\Part.class","com.jse.http.Part");
		System.out.println(Refs.invokeMethod(c,"name1"));
	}
}
